/* initguid.h must be included BEFORE dxdiag.h.
    This solves linking issues with errors caused by 
    DEFINE_GUID -- specifically CLSID_DxDiagProvider and 
    IID_IDxDiagProvider.  Probably, the WINE headers differ in some
    minor way from the Windows headers.
*/
#include <initguid.h>
#include <dxdiag.h>
#include <oleauto.h>
#include <oaidl.h>
#include <stdio.h>
#include <wchar.h>
#include <ctype.h>

#define MAX_STRING_LEN 1024

void indent(int depth) {
    int i; 
    for (i = 0; i < depth; i++) {
        printf(" ");
    }
}

void exploreContainer(int depth, IDxDiagContainer* parent) {
    DWORD numContainers, numProps;
    int i, j;
    WCHAR prop[MAX_STRING_LEN];
    VARIANT var;
    HRESULT hr;
    IDxDiagContainer* child;

    /* Get number of child containers */
    IDxDiagContainer_GetNumberOfChildContainers(parent, &numContainers);
    indent(depth-1);
    printf("Number of child containers=%d\n\n", (int)numContainers);
    
    /* Check out the children */
    for(i = 0; i < numContainers; i++) {
        IDxDiagContainer_EnumChildContainerNames(parent, i, (LPWSTR)&prop, MAX_STRING_LEN);
        indent(depth);
        printf("Container: %ls\n", prop);
        IDxDiagContainer_GetChildContainer(parent, prop, &child);
        
        /* Get the number of properties */
        IDxDiagContainer_GetNumberOfProps(child, &numProps);
        indent(depth);
        printf("Number of properties: %d\n", (int)numProps);

        /* Print out the values of the properties */
        for (j = 0; j < numProps; j++) {
            IDxDiagContainer_EnumPropNames(child, j, (LPWSTR)&prop, MAX_STRING_LEN);
            hr = IDxDiagContainer_GetProp(child, prop, &var);
            indent(depth);
            VariantChangeType(&var,&var,VARIANT_ALPHABOOL,VT_BSTR);
            printf("Property: %ls: %ls\n", prop, V_BSTR(&var));
            VariantClear(&var);
        }

        /* Recurse */
        exploreContainer(depth+1, child);
    }
}

char* convertUnicodeToAsciiUpper(WCHAR* unicode){
	int i;
	char ascii[MAX_STRING_LEN];
	char *upper = (char*)unicode;
	sprintf(ascii, "%ls", unicode);
	for (i = 0; ascii[i] != '\0'; i++){
		upper[i] = (char)toupper((int)ascii[i]);
	}
	upper[i] = '\0';
	return upper;
}

void generateCConstants(int depth, IDxDiagContainer* parent) {
    DWORD numContainers, numProps;
    int i, j;
    WCHAR prop[MAX_STRING_LEN];
    IDxDiagContainer* child;

    /* Get number of child containers */
    IDxDiagContainer_GetNumberOfChildContainers(parent, &numContainers);
    indent(depth-1);
    printf("Number of child containers=%d\n\n", (int)numContainers);

    /* Check out the children */
    for(i = 0; i < numContainers; i++) {
        IDxDiagContainer_EnumChildContainerNames(parent, i, (LPWSTR)&prop, MAX_STRING_LEN);
        indent(depth);
        printf("%ls\n\n", prop);
        IDxDiagContainer_GetChildContainer(parent, prop, &child);

        /* Get the number of properties */
        IDxDiagContainer_GetNumberOfProps(child, &numProps);
        indent(depth);
        printf("Number of properties: %d\n", (int)numProps);

        /* Print the enum all caps variables */
        for (j = 0; j < numProps; j++) {
            IDxDiagContainer_EnumPropNames(child, j, (LPWSTR)&prop, MAX_STRING_LEN);
            indent(depth);
            printf("DXDIAG_PROP_%s,\n", convertUnicodeToAsciiUpper(prop));
        }
        
        /* Print string label */
        for (j = 0; j < numProps; j++) {
            IDxDiagContainer_EnumPropNames(child, j, (LPWSTR)&prop, MAX_STRING_LEN);
            indent(depth);
            printf("L\"%ls\",\n", prop);
        }

        /* Recurse */
        generateCConstants(depth+1, child);
    }
}

int main() {
    HRESULT hr;
    DXDIAG_INIT_PARAMS params;
    IDxDiagProvider* pddp = NULL;
    IDxDiagContainer* pddc = NULL;
    /*
    HINSTANCE hInstance = GetModuleHandleW(0);
	*/

    fwprintf(stderr, L"Test fwprintf\n");

    /* Initialize COM? */
    CoInitialize(NULL);
    hr = CoCreateInstance(&CLSID_DxDiagProvider, NULL, CLSCTX_INPROC_SERVER,
        &IID_IDxDiagProvider, (LPVOID*)&pddp);
    if (FAILED(hr))
        goto failed;

    /* Initialize DxDiagProvider? */
    params.dwSize = sizeof(params);
    params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
    params.bAllowWHQLChecks = TRUE;
    params.pReserved = NULL;
    hr = IDxDiagProvider_Initialize(pddp, &params);
    if (FAILED(hr))
        goto failed;

    /* Get root container */
    hr = IDxDiagProvider_GetRootContainer(pddp, &pddc);
    if (FAILED(hr))
        goto failed;

    /* Peruse all containers and properties */
    exploreContainer(0, pddc);
/*    generateCConstants(0, pddc);*/

    /* Done */
    return 0;
failed:
    printf("Failed");
    return 1;
}


